package server;

/**
 *@author Adam
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;
import source.ControlBar;

import storage.SongObject;

public class Server {

	public String host = "";
	public int port = -1;
	public static final String SERVICE_TYPE = "uss.local.";
	Double duration;
	int numSockets = 0;
	SocketConnect[] openSockets = new SocketConnect[100]; 
	String hifiAddress = "";
	String hifiRMIService = "";
	static String SERVICE_NAME = "Server_Service";
	static int SERVICE_PORT = 6000;
	ServerSocket serverSocket;
	public int backlog = 5;



	public Server(){	
		BonjourListener sl = new BonjourListener(SERVICE_TYPE, this);

		try
		{
			serverSocket = new ServerSocket(SERVICE_PORT, backlog);
			System.out.println("The server has started and is listening on "+SERVICE_PORT);
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}
		catch (SecurityException se)
		{
			se.printStackTrace();
		}
	}

	public void serviceDiscovered(String myHost, int myPort, String myServiceName){
		host = myHost;
		port = myPort;
		openSockets[numSockets] = new SocketConnect(host, port, this);
		openSockets[numSockets].start();
		numSockets++;
	}

	public void foundHifi(String RMIName, String address, String size){
		try{
			FileWriter fstream = new FileWriter("./src/server/Hifis.xml",true);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(address +","+ RMIName + "," + size + "\n");
			out.close();
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	public void foundDisplay(String RMIName, String address, String size){
		try{
			FileWriter fstream = new FileWriter("./src/server/Displays.xml",true);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(address +","+ RMIName + "," + size + "\n");
			out.close();
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	public void foundStorage(String RMIName, String StorageAddress){
		RMIStorageClient rmisc = new RMIStorageClient(RMIName);
		rmisc.begin(StorageAddress);
		//		int p = rmisc.getPort();
		//		System.out.println("sdfljsdlkfjsdlkfjlskjfldjslf " + p);
		Vector v = rmisc.getSongs();
		System.out.println(v.size());
		for (int i = 0; i<v.size(); i++){
			System.out.println(v.elementAt(i).toString());
			SongObject so = (SongObject) v.elementAt(i);
			try{
				FileWriter fstream = new FileWriter("./src/server/FullMp3s.xml",true);
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(so.toString() + "<RMIName>" +RMIName+ "</RMIName> \n");
				out.close();
			}catch (Exception e){
				e.printStackTrace();
			}
		}
	}

	public boolean useThisDisplay(String current, String newSize){
		int first = 0;
		int second = 0;
		if (current.equals("")){}
		else if (current.equals("small")){first = 1;}
		else if (current.equals("medium")){first = 2;}
		else if (current.equals("large")){first = 3;}
		if (newSize.equals("")){}
		else if (newSize.equals("small")){second = 1;}
		else if (newSize.equals("medium")){second = 2;}
		else if (newSize.equals("large")){second = 3;}
		if (second > first){ return true;}
		else return false;	
	}

	public boolean useThisHifi(String current, String newSize){
		int first = 0;
		int second = 0;
		if (current.equals("")){}
		else if (current.equals("quiet")){first = 1;}
		else if (current.equals("medium")){first = 2;}
		else if (current.equals("loud")){first = 3;}
		if (newSize.equals("")){}
		else if (newSize.equals("quiet")){second = 1;}
		else if (newSize.equals("medium")){second = 2;}
		else if (newSize.equals("loud")){second = 3;}
		if (second > first){ return true;}
		else return false;	
	}


	public void streamSong(String filename){
		System.out.println("i want to stream the file " + filename);
		String contents = "";
		try{
			FileReader fr = new FileReader("./src/server/FullMp3s.xml");
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			while((s = br.readLine()) != null) {
				if (s.contains(filename)){
					contents = s;
					break;
				}
				System.out.println("contents are " + contents);
			}
			fr.close();
		} catch (Exception e){
			e.printStackTrace();
		}
		int begin = contents.indexOf("<RMIName>");
		int end = contents.indexOf("</RMIName>");
		String RMIName = contents.subSequence(begin, end).toString();
		RMIName = RMIName.substring(9);
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!" + RMIName);
		begin = contents.indexOf("<location>");
		end = contents.indexOf("</location>");
		String address = contents.subSequence(begin, end).toString();
		address = address.substring(10);
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!" + address);
		RMIStorageClient rmisc = new RMIStorageClient(RMIName);
		rmisc.begin(address);

		int duration =(int) rmisc.transmitMusicTrack(filename, hifiAddress);

		System.err.println(duration);

		try {
			Thread.currentThread().sleep(1000*duration);
		} catch (InterruptedException ie) {
			System.out.println(ie);
		}

		rmisc.stopTransmit(); 
	}


	public void addSongToPlaylist(String filename){
		System.out.println("Client wants to play the file " + filename);
		String contents = "";
		try{
			FileReader fr = new FileReader("./src/server/FullMp3s.xml");
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			while((s = br.readLine()) != null) {
				if (s.contains(filename)){
					contents = s;
					break;
				}
				System.out.println("contents are " + contents);
			}
			fr.close();
		} catch (Exception e){
			e.printStackTrace();
		}
		int begin = contents.indexOf("<RMIName>");
		int end = contents.indexOf("</RMIName>");
		String RMIName = contents.subSequence(begin, end).toString();
		RMIName = RMIName.substring(9);
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!" + RMIName);
		begin = contents.indexOf("<location>");
		end = contents.indexOf("</location>");
		String address = contents.subSequence(begin, end).toString();
		address = address.substring(10);
		try{
			FileWriter fstream = new FileWriter("./src/server/ThePlaylist.xml",true);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(filename + "," + RMIName + "," + address);
			out.close();
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	public void startPlay(){
		int b = -2;
		String listAfter = "";
		String filename = "";
		try{
			FileInputStream fis = new FileInputStream(new File("./src/server/ThePlaylist.xml"));  
			b = fis.read();
		} catch (Exception e){
			e.printStackTrace();
		}



		if (b > -1){  

			do{
				try{
					FileReader fr = new FileReader("./src/server/ThePlaylist.xml");
					BufferedReader br = new BufferedReader(fr);
					String s = "";  
					s = br.readLine();
					StringTokenizer st = new StringTokenizer(s,",");
					filename = st.nextToken();
					System.out.println("file that will start playing is " + filename);
					String another = "";
					while((another = br.readLine()) != null) {
						listAfter += another + "\n";
					}
					fr.close();
				} catch (Exception e){
					e.printStackTrace();
				}
				try{
					FileWriter fstream = new FileWriter("./src/server/ThePlaylist.xml");
					BufferedWriter out = new BufferedWriter(fstream);
					out.write(listAfter);
					out.close();
				}catch (Exception e){
					e.printStackTrace();
				}
				streamSong(filename);

			}while(b>-1);
		}



		else{
			System.out.println("The playlist is empty!");

		}
	}

	public void goDisplay(){
		String displayDetails = "";
		String ip = "";
		String RMIService = "";
		String size = "";
		String contents = "";
		try{
			FileReader fr = new FileReader("./src/server/Displays.xml");
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			while((s = br.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(s, ",");
				String tempIp = st.nextToken();
				String tempRMIService = st.nextToken();
				String tempSize = st.nextToken();
				if (useThisDisplay(size, tempSize) == true){
					System.out.println("found a better display! gonna use that now!");
					ip = tempIp;
					RMIService = tempRMIService;
					size = tempSize;
				}
			}
			System.out.println("displayDetails = " + displayDetails);
			fr.close();
		} catch (Exception e){
			e.printStackTrace();
		}
		System.out.println("ip for hifi is " +ip);
		System.out.println("RMISERveice for display is " + RMIService);
		RMIDisplayClient rmidc = new RMIDisplayClient(RMIService);
		rmidc.begin(ip); 

		try{
			FileReader fr = new FileReader("./src/server/ThePlaylist.xml");
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			while((s = br.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(s,",");
				String playListfile = st.nextToken();
				FileReader fr2 = new FileReader("./src/server/FullMp3s.xml");
				BufferedReader br2 = new BufferedReader(fr);
				String ss = "";
				while((ss = br2.readLine()) != null) {
					if(ss.contains(playListfile)){
						contents = contents + ss + ",";
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		rmidc.displayInfo(contents);
	}

	public void hifiStream(){
		String hifiDetails = "";
		String ip = "";
		String RMIService = "";
		String size = "";
		try{
			FileReader fr = new FileReader("./src/server/Hifis.xml");
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			while((s = br.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(s, ",");
				String tempIp = st.nextToken();
				String tempRMIService = st.nextToken();
				String tempSize = st.nextToken();
				if (useThisHifi(size, tempSize) == true){
					System.out.println("found a louder hifi! gonna use that now!");
					ip = tempIp;
					RMIService = tempRMIService;
					size = tempSize;

				}
			}
			System.out.println("hifiDetails = " + hifiDetails);
			fr.close();
		} catch (Exception e){
			e.printStackTrace();
		}
		hifiAddress = ip;
		hifiRMIService = RMIService; 
		System.out.println("ip for hifi we're about to stream on is " +ip);
		System.out.println("RMISERveice for hifi we're about to stream on is " + RMIService);
		RMIHifiClient rmihc = new RMIHifiClient(RMIService);
		rmihc.begin(ip);
		goDisplay();
		rmihc.streamFrom("rtp://" + ip + ":5000/audio");
	}

	public void hifiPause(){
		RMIHifiClient rmihc = new RMIHifiClient(hifiRMIService);
		rmihc.begin(hifiAddress); 
		rmihc.pauseStream();
	}

	public void hifiStop(){
		RMIHifiClient rmihc = new RMIHifiClient(hifiRMIService);
		rmihc.begin(hifiAddress); 
		rmihc.stopStream();
	}

	public void hifiPlay(){
		RMIHifiClient rmihc = new RMIHifiClient(hifiRMIService);
		rmihc.begin(hifiAddress);
		rmihc.playStream();
	}

	public void killHifi(){
		RMIHifiClient rmihc = new RMIHifiClient(hifiRMIService);
		rmihc.begin(hifiAddress);
	}

	public void deviceIsDead(String host, int port, String RMIService){
		System.out.println("A DEVICE HAS DIED, TRYING TO RESTORE CONSISTENCY!");
		if (RMIService.startsWith("hifi")){
			String contents = "";
			if (hifiAddress.equals(host)){
				hifiAddress = "";
			}
			try{
				FileReader fr = new FileReader("./src/server/Hifis.xml");
				BufferedReader br = new BufferedReader(fr);
				String s = "";
				while((s = br.readLine()) != null) {
					if (s.contains(host) == false && s.contains(RMIService) == false){
						contents = contents + s + "\n";
					}
					System.out.println(contents);
				}
				fr.close();
			} catch (Exception e){
				e.printStackTrace();
			}
			try{
				// Create file 
				FileWriter fstream = new FileWriter("./src/server/Hifis.xml");
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(contents);
				//Close the output stream
				out.close();
			}catch (Exception e){//Catch exception if any
				System.err.println("Error: " + e.getMessage());
			}
		}
		else if (RMIService.startsWith("storage")){
			String contents = "";
			try{
				FileReader fr = new FileReader("./src/server/FullMp3s.xml");
				BufferedReader br = new BufferedReader(fr);
				String s = "";
				while((s = br.readLine()) != null) {
					if (s.contains(host) == false && s.contains(RMIService) == false){
						contents = contents + s + "\n";
					}
					System.out.println(contents);
				}
				fr.close();
			} catch (Exception e){
				e.printStackTrace();
			}
			try{
				// Create file 
				FileWriter fstream = new FileWriter("./src/server/FullMp3s.xml");
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(contents);
				//Close the output stream
				out.close();
			}catch (Exception e){//Catch exception if any
				System.err.println("Error: " + e.getMessage());
			}
		}
		else if (RMIService.startsWith("display")){
			String contents = "";
			try{
				FileReader fr = new FileReader("./src/server/Displays.xml");
				BufferedReader br = new BufferedReader(fr);
				String s = "";
				while((s = br.readLine()) != null) {
					if (s.contains(host) == false && s.contains(RMIService) == false){
						contents = contents + s + "\n";
					}
					System.out.println(contents);
				}
				fr.close();
			} catch (Exception e){
				e.printStackTrace();
			}
			try{
				// Create file 
				FileWriter fstream = new FileWriter("./src/server/Displays.xml");
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(contents);
				//Close the output stream
				out.close();
			}catch (Exception e){//Catch exception if any
				System.err.println("Error: " + e.getMessage());
			}
		}
	}

	public void listen()
	{
		while(true)
		{
			try
			{
				Socket socket = serverSocket.accept();
				BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				String message = inFromClient.readLine();
				//System.out.println("Message from client: " + message);
				PrintWriter outToClient = new PrintWriter(socket.getOutputStream(), true);
				if(message.equals("CLIENT"))
					outToClient.println("SERVER");
				inFromClient.close();
				socket.close();
			}
			catch(IOException ioe)
			{
				ioe.printStackTrace();
			}
			catch(SecurityException se)
			{
				se.printStackTrace();
			}
		}
	}


	public static void main(String[] args) throws IOException{
		Server server = new Server();
		CThread playTrackList;
		ServiceInfo info;
		JmDNS jmdns;
		jmdns = JmDNS.create();
		info = ServiceInfo.create(SERVICE_TYPE, SERVICE_NAME, SERVICE_PORT,0,0,"a_property=some_value");
		jmdns.registerService(info);
		System.out.println("Registered Service as "+info);
		try
		{
			System.setSecurityManager(new RMISecurityManager());
			System.out.println("Security Manager Set.");
			RMIServerImpl Server = new RMIServerImpl();
			System.out.println("RMISERVER Instansiated");
			Naming.rebind("SAMPLE-SERVER" , Server);
			System.out.println("Server name binded.");
			System.out.println("Server waiting.....");
		}
		catch (java.net.MalformedURLException me)
		{
			System.out.println("Malformed URL: " + me.toString());
		}
		catch (RemoteException re)
		{
			System.out.println("Remote exception: " + re.toString());
		}
		server.listen();
		jmdns.unregisterService(info);
		jmdns.close();		
		while(true){
			System.out.println("Start typing, then press <return>");
			BufferedReader in =
				new BufferedReader(new InputStreamReader(System.in));
			String s = null;
			try {
				s = in.readLine();
				System.out.println("Echo: " + s);
				if (s.equals("1")){
					System.out.println("add song to playlist!");
					server.addSongToPlaylist("Satelight.mp3");
					server.addSongToPlaylist("Alice.mp3");
				}
				else if (s.equals("2")){
					System.out.println("hifi stream go!");
					server.hifiStream();
				}
				else if (s.equals("3")){
					System.out.println("playing song on playlist!");
//					server.startPlay();
					playTrackList = new CThread();
				}
				else if (s.equals("4")){
					System.out.println("stopping hifi stream!");
					server.hifiStop();
				}
				else if (s.equals("5")){
					System.out.println("killing storage!");

				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}


class CThread extends Server implements Runnable
{
	Thread tt = null;
	public CThread()
	{

		tt = new Thread(this,"CThread");
		tt.start();
	}

	public void run()
	{

		startPlay();

	}
}



